﻿using System;
using System.Globalization;
using System.Linq;
using System.Web.Routing;

namespace Kaiser.MvcBase.Route {
    public class LowerCaseUrlRoute : System.Web.Routing.Route {
        private static readonly string[] RequiredKeys = new[] {"area", "controller", "action"};

        public LowerCaseUrlRoute(string url, IRouteHandler routeHandler)
            : base(url, routeHandler) {}

        public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, IRouteHandler routeHandler)
            : base(url, defaults, routeHandler) {}

        public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints,
                                 IRouteHandler routeHandler)
            : base(url, defaults, constraints, routeHandler) {}

        public LowerCaseUrlRoute(string url, RouteValueDictionary defaults, RouteValueDictionary constraints,
                                 RouteValueDictionary dataTokens, IRouteHandler routeHandler)
            : base(url, defaults, constraints, dataTokens, routeHandler) {}

        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
            lowerRouteValues(requestContext.RouteData.Values);
            lowerRouteValues(values);
            lowerRouteValues(Defaults);
            return base.GetVirtualPath(requestContext, values);
        }

        private static void lowerRouteValues(RouteValueDictionary values) {
            foreach (var key in RequiredKeys) {
                if (values.ContainsKey(key) == false) continue;

                var value = values[key];
                if (value == null) continue;

                var valueString = Convert.ToString(value, CultureInfo.InvariantCulture);
                if (string.IsNullOrEmpty(valueString)) continue;

                values[key] = valueString.ToLower();
            }

            var otherKyes = values.Keys
                                  .Except(RequiredKeys, StringComparer.InvariantCultureIgnoreCase)
                                  .ToArray();

            foreach (var key in otherKyes) {
                var value = values[key];
                values.Remove(key);
                values.Add(key.ToLower(), value);
            }
        }
    }
}